Custom Data Filters

This page is about using Custom Data. In order to use it, you must first add Custom Data to indexed items.

Custom data that is stored in URL GET encoded format can be used as a filter data source, for search results. For example if documents in the index have a custom data field named 'publishDate', which holds yyyy-mm-dd formatted data, then it is possible to filter out documents that do not match a filter's date range.

Filter types

There are several types of underlying filter that can be used:

Filter Control types

The underlying filters described above can be presented to the user with a variety of Controls (where it makes sense to do so). For example an 'int' filter might be presented to the user with 2 text boxes (allowing entry of an integer range), or the 'int' filter might be presented to the user with a dropdown menu, or a group of checkboxes.

Adding and defining filter controls

To add a filter control to the page, add a DIV with class 'sew_filterControl' (remember it is possible to have multiple CSS classes apply to an element, just separate with a space).

HTML
        <div class="dateFilter sew_filterControl">
            <!--{   "FieldName":    "publishDate", 
                    "ControlType":  "calendar", 
                    "Label":        "Recipe date:", 
                    "Type":         "date", 
                    "Options":      []}-->
        </div>

    

Inside of the DIV is a comment containing JSON formatted meta data. JSON formatting uses the same simple object notation used by Javascript, essentially; "[]" means an array, "{}" means an object, and inside of the braces appear "property name: "value".

Filter definition (properties and options)

The properties set inside of the JSON meta data will control what data field the filter works with, how the Control appears and how it operates, the table below shows possible values for each property.

Use care not to make syntax errors when writing JSON meta data, there are various online JSON validators available

FieldName ControlType Type Label Options OptionLabelFormat GetLiveDataFromServer
Name of the CustomData field Control type to use Underlying filter type User friendly label Options specific to the control For labels that are based on option values Whether to show filter options based on search result data
Calendar/date-pickers * "calendar" "date" text shown to the left of the date pickers [] - if no options specified
["yyyy-mm-dd"] - to specify the earliest possible date available
["yyyy-mm-dd", "yyyy-mm-dd"] - to specify the selectable date range
n/a "true"** or "false"
Checkboxes * "checkboxes" "int"
"stringor"
"stringand"
"stringlistand"
"stringlistor"
text shown to the left of the checkboxes [{ "value": "option1", "label": "label1" }, { "value": "option2", "label": "label2" }, ...] - a checkbox is shown for each array element, with the checkbox label and filter selection set to the "label" and "value" specified respectively. n/a "true"** or "false"
Integer range checkboxes * "checkboxesIntRange" "int" text shown to the left of the checkboxes [{ "value":"0-2000" }, { "value":"2000-5000"}, ...] - a checkbox is shown for each array element, with the checkbox label set to the "value" specified according to the OptionLabelFormat. The values specified should be in the format of low-high. "${0} - ${1}" - where ${0} is replaced with the low-end option and ${1} is replaced with the high-end option. "true"** or "false"
Drop down menu * "dropdown" "int"
"stringor"
"stringand"
"stringlistor"
"stringlistand"
text shown to the left of the SELECT [{ "value": "option1" }, { "value": "option2" }, ...] - an OPTION is added for each array element, with the text set to the "value" specified. n/a "true"** or "false"
Integer range textboxes * "textboxesIntRange" "int" text shown to the left of the first textbox n/a n/a n/a (no options shown to user)
Geolocation/distance based range * "geolocation" "geolocation" 2 labels, first is for search origin and second is for distance drop down [{"name":"option1 name", "value": "option1" }, {"name":"option2 name", "value": "option2" }, ...] - an OPTION is added for each array element, with the text set to the "name" specified. n/a n/a (no options shown to user)

* - specify the field's name (that the filter should operate on) as it appears in the CustomData.

** - use with caution, this can cause extra work on the server (sampling and sorting data), extra data transmission to client (up to 500 unique data items). It is suggested that if there are thousands of different data values assigned to custom data, or many tens of thousands of possible results that this option not be used.

Some example filter definitions.

HTML

    <!--Geolocation selection (see section below on geolocation)-->
    <div class="sew_filterControl">
        <!-- {"FieldName":"geolocation", "ControlType":"geolocation","Label":"Location:", "Label2":"Within:", 
                    "Type":"geolocation", 
                    "Options":[{"name":"Any", "value": "" }, {"name":"1 mile", "value": "0-1" }, 
                                {"name":"5 miles", "value": "0-5" }, {"name":"10 miles", "value": "0-10" }, 
                                { "name":"20 miles","value": "0-20" }, {"name":"50 miles", "value": "0-50" }, 
                                {"name":"100 miles", "value": "0-100" }], "GetLiveDataFromServer": "false"} -->
    </div>
    

    <!--Date picker-->
    <div class="sew_dateFilter sew_filterControl">
        <!-- {"FieldName":"manufacturedDate", "ControlType":"calendar", 
                "Label":"Manufacture date:", "Type":"date", "Options":["2000-01-01"]}-->
    </div>
    
    <!--Checkbox chooser for manufacturer-->         
    <div class="sew_stringOrFilter sew_filterControl">
        <!-- {"FieldName":"make", "ControlType":"checkboxes",
                "Label":"Manufacturer:", "Type":"stringor", "Options":[{ "value": "Ford" }, 
                    { "value": "Toyota"  }, { "value": "Volkswagon"  }], 
                "GetLiveDataFromServer": "true"}-->
    </div>
                
    <!--Drop down model year selector-->
    <div class="sew_intListFilter sew_filterControl">
        <!-- {"FieldName":"modelYear", "ControlType":"dropdown",
                "Label":"Model year:", "Type":"int", "Options":[{ "value": "1979" }, { "value": "1980" }, 
                        { "value": "1987" }, { "value": "2010" }, { "value": "2013" }, 
                        { "value": "2014" }], "GetLiveDataFromServer": "true"} -->
    </div>
    
    <!--Checkbox based price range selector-->
    <div class="sew_intRangeFilter sew_filterControl">
        <!-- {"FieldName":"price", "ControlType":"checkboxesIntRange","Label":"Price:", 
                    "Type":"int", "OptionLabelFormat":"${0} - ${1}", 
                    "Options":[{  "value":"0-2000" }, {  "value":"2000-5000" }, {  "value":"5000-10000" }, 
                    { "value":"10000-20000" }, { "value":"20000-50000" }], 
                    "GetLiveDataFromServer": "true"} -->
    </div>
    
    <!--2 textbox int range selector-->
    <div class="sew_intRangeFilter sew_filterControl">
        <!-- {"FieldName":"price", "ControlType":"textboxesIntRange","Label":"Price:", "Type":"int", 
                    "Options":[], "GetLiveDataFromServer": "false"} -->
    </div>
              
    <!--Or based checkbox selector for features-->
    <div class="sew_stringOrFilter sew_filterControl">
        <!-- {"FieldName":"options", "ControlType":"checkboxes","Label":"Options:", "Type":"stringlistand", 
                    "Options":[{ "value": "Auto" }, { "value": "Electric windows"  }, { "value": "Manual"  }, 
                    { "value": "Hatchback"  }, { "value": "AC"  }], "GetLiveDataFromServer": "true"}-->
    </div>


A complete example page with 3 filters.

.NET Version Note

If you are using .NET 5 or .NET 2, you must also add one these lines in the examples below

Javascript

keyotiSearch.setServiceType('core'); //for .NET 5

keyotiSearch.setServiceType('asmx'); //for .NET 2

HTML
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title></title>
        <link href="/Keyoti_SearchEngine_Web_Common/SearchUnit.css" rel="stylesheet" />
        <script src="/Keyoti_SearchEngine_Web_Common/SearchUnit.js"></script>
    </head>
    <body>
        <div id="sew_searchBoxControl"></div>

        <div id="sew_filterControls">

                <div class="sew_filterControl">
                    <!--{
                        "FieldName":    "manufacturedDate", 
                        "ControlType":  "calendar", 
                        "Label":        "Manufacture date:", 
                        "Type":         "date", 
                        "Options":      ["2000-01-01"]}-->
                </div>
             
                <div class="sew_filterControl">
                    <!--{
                        "FieldName":    "make", 
                        "ControlType":  "checkboxes",
                        "Label":        "Manufacturer:", 
                        "Type":         "stringor", 
                        "Options":      [   { "value": "Ford" }, 
                                            { "value": "Toyota"  }, 
                                            { "value": "Volkswagon"  }], 
                        "GetLiveDataFromServer":    "true"}-->
                </div>
                
                <div class="sew_filterControl">
                    <!-- {
                        "FieldName":    "modelYear", 
                        "ControlType":  "dropdown",
                        "Label":        "Model year:", 
                        "Type":         "int", 
                        "Options":      [   { "value": "1979" }, 
                                            { "value": "1980" }, 
                                            { "value": "1987" }, 
                                            { "value": "2010" }, 
                                            { "value": "2013" }, 
                                            { "value": "2014" }], 
                        "GetLiveDataFromServer":    "true"} -->
                </div>

        </div>

        <div id="sew_searchResultControl"></div>
    </body>
</html>

    

Updating results based on filter selection changes

By default, when the user changes a selection the results will automatically update (a new search is initiated to do this). This may not be ideal user experience if searches are slower than a second or two (due to large index or busy server), or if it is preferable to let the user update all of their choices before refreshing the results. To use a button to update results use the following code:

Javascript / HTML
    ...
        <script type="text/javascript">
            keyotiSearch.updateOnOptionChange = false;
        </script>
    ...
        <input type="button" onclick="keyotiSearch.showPage(1, true)" value="Update results" />

Geolocation filter

The geolocation filter can search for result items that are within a certain distance of the 'search origin' (the origin may be the user's current location or a place that they want to search from).

Specifying an indexed item (document) location

To be included in a geospatial search, an item must have its latitude and longitude specified in the Custom Data field (using decimal notation). Eg. for Vancouver, BC:

CustomData Field
    geolocation=49.291985,-123.138668

See how to add Custom Data to indexed items.

Geospatial searching without a map

  1. Ensure indexed documents (items) has geolocation Custom Data added (see above).
  2. Add a Geolocation Filter control to the search page.
    Javascript / HTML
        <div class="sew_filterControl"><!-- {"FieldName":"geolocation", 
                                                        "ControlType":"geolocation","Label":"Location:", "Label2":"Within:", 
                                                        "Type":"geolocation", 
                                                        "Options":[{"name":"Any", "value": "" }, {"name":"1 mile", "value": "0-1" }, 
                                                        {"name":"5 miles", "value": "0-5" }, {"name":"10 miles", "value": "0-10" }, 
                                                        { "name":"20 miles","value": "0-20" }, {"name":"50 miles", "value": "0-50" },   
                                                        {"name":"100 miles", "value": "0-100" }], "GetLiveDataFromServer": "false"} -->
    
        </div>
                
  3. The control contains a textbox for the user to enter their search location in, by itself it will not actually do anything, but it can be worked with in Javascript to set the search location coordinates.

The geolocation filter also has other functions in its API that may be useful, for example to hide the location entry elements.

Javascript
    //Get all geo filters on the page
    var geoFilters = keyotiCustomDataFilters.getGeoLocationFilterControls();
    //Set the home location, where searches are from
    geoFilters[0].setHomeLocation(50.859784, 0.578471, "Hastings");
    //Access and hide the location textbox and label
    geoFilters[0].getHomeLocationTextBoxElement().hide();
    geoFilters[0].getHomeLocationLabelElement().hide();
        

Using Filters Programmatically

To use filters for programmatic searching please see the programmatic searching page.